fs/promises и потокиNode.js предоставляет богатые возможности для работы с файловой системой. В этой записи будет два ключевых подхода: обещания (fs/promises) и потоки (Streams), с особым акцентом на потоках как наиболее эффективном способе работы с большими файлами.
Модуль fs/promises предоставляет promise-версии всех основных методов модуля fs. Это упрощает код и делает его более читаемым.
async function copyFile() {
const data = await readFile('source.txt', 'utf-8');
await writeFile('destination.txt', data);
}
Этот подход хорош для небольших файлов. Но с большими файлами возникают проблемы: файл читается/записывается целиком в память, что может привести к утечкам памяти и тормозам. Прикинь загружать текст размером 8 гигов с ограничением VDS в 4? Вот за этим стримы и нужны.
Потоки позволяют обрабатывать данные по частям, не загружая всё в память. В Node.js есть четыре основных типа потоков:
Readable — читающий поток (например, чтение из файла)
Writable — записывающий поток (например, запись в файл)
Duplex — двунаправленный (и чтение, и запись)
Transform — как Duplex, но с преобразованием данных на лету
import { createReadStream, createWriteStream } from 'fs';
const readable = createReadStream('bigfile.txt');
const writable = createWriteStream('copy.txt');
readable.pipe(writable);
Метод pipe передаёт данные из одного потока в другой. Это самый эффективный способ копировать большие файлы. Можно вручную читать и записывать из одного потока в другой, даже делать при этом приобразования, но такой метод чуть менее эффективнее, чем трансформация и pipe.
P.s. не делай так, как я описал выше.
Иногда нужно обрабатывать данные между чтением и записью:
import { createReadStream, createWriteStream } from 'fs';
const readStream = createReadStream('input.txt', { encoding: 'utf-8' });
const writeStream = createWriteStream('output.txt');
readStream.on('data', (chunk) => {
const upper = chunk.toUpperCase();
writeStream.write(upper);
});
readStream.on('end', () => {
writeStream.end();
});
Но такой способ не очень эффективен сам по себе. Вот лучше:
import { Transform } from 'stream';
const upperCaseTransform = new Transform({
transform(chunk, encoding, callback) {
const transformed = chunk.toString().toUpperCase();
callback(null, transformed);
}
});
И подключение его к цепочке:
import { createReadStream, createWriteStream } from 'fs';
createReadStream('input.txt')
.pipe(upperCaseTransform)
.pipe(createWriteStream('output.txt'));
Знаю, ты прогер от бога и ошибок не делаешь, но на всякий случай:
readStream.on('error', console.error);
writeStream.on('error', console.error);
| Метод | Подходит для |
|---|---|
| fs/promises | Небольшие файлы, простой код |
| Потоки | Большие файлы, обработка на лету |
Если кто-то желает присоединиться - добро пожаловать.
-Jame